/**
 *  This file is part of Chronicles.
 *
 *  Chronicles is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Chronicles is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Chronicles.  If not, see <http://www.gnu.org/licenses/>.
 */
package net.wookimus.chronicles;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteCursor;
import android.database.sqlite.SQLiteCursorDriver;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQuery;
import android.util.Log;

import net.wookimus.chronicles.R;

/**
 * The database adapter contains the basic logic for creating, updating, and
 * connecting to the Chronicles database. 
 */
public class ChroniclesDatabase extends SQLiteOpenHelper {
	private static final String DATABASE_NAME = "chronicles";
	private static final int DATABASE_VERSION = 2;

	private final Context mContext;

    /** Constructor */
    public ChroniclesDatabase(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        this.mContext = context;
    }

    /**
     * Execute all of the SQL statements in the String[] array
     * @param db The database on which to execute the statements
     * @param sql An array of SQL statements to execute
     */
    private void execMultipleSQL(SQLiteDatabase db, String[] sql){
        for( String s : sql ) {
            if (s.trim().length()>0) {
                db.execSQL(s);
            }
        }
    }

    /** Called when it is time to create the database */
    @Override
    public void onCreate(SQLiteDatabase db) {
        String[] sql = mContext.getString(
                R.string.ChroniclesDatabase_onCreate).split("\n");
        db.beginTransaction();
        try {
            // Create tables & test data
            execMultipleSQL(db, sql);
            db.setTransactionSuccessful();
        } catch (SQLException e) {
            Log.e("Error creating tables and debug data", e.toString());
        } finally {
            db.endTransaction();
        }
    }

    /** Called when the database must be upgraded */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.w(mContext.getString(R.string.app_name),
                "Upgrading database from version " + oldVersion + " to " +
                newVersion + ", which will destroy all old data");

        String[] sql = mContext.getString(
                R.string.ChroniclesDatabase_onUpgrade).split("\n");
        db.beginTransaction();
        try {
            // Create tables & test data
            execMultipleSQL(db, sql);
            db.setTransactionSuccessful();
        } catch (SQLException e) {
            Log.e("Error creating tables and debug data", e.toString());
        } finally {
            db.endTransaction();
        }

        // TODO: We should not be dropping databases!
        onCreate(db);
    }
	
	public static class CharactersCursor extends SQLiteCursor {
		private static final String QUERY = "SELECT _id, name, quote "
				+ "FROM characters " + "ORDER BY name";

		CharactersCursor(SQLiteDatabase db, SQLiteCursorDriver driver,
				String editTable, SQLiteQuery query) {
			super(db, driver, editTable, query);
		}

		private static class Factory implements SQLiteDatabase.CursorFactory {
			public Cursor newCursor (SQLiteDatabase db, SQLiteCursorDriver driver, String editTable, SQLiteQuery query) {
				return new CharactersCursor(db, driver, editTable, query);
			}
		}
		public long getColCharactersId() {
			return getLong(getColumnIndexOrThrow("characters._id"));
		}
		public String getColCharactersName() {
			return getString(getColumnIndexOrThrow("characters.name"));
		}
		public String getColCharactersQuote() {
			return getString(getColumnIndexOrThrow("characters.quote"));
		}
	}

    /**
     * Add a new character to the database.
     * @param name			The name of the character
     * @param quote			A notable quote or saying for the character
     */
    public void addCharacter(String name, String quote){
        ContentValues map = new ContentValues();
        map.put("name", name);
        map.put("quote", quote);
        try{
            getWritableDatabase().insert("characters", null, map);
        } catch (SQLException e) {
            Log.e("Error writing new character", e.toString());
        }
    }

    /**
     * Update a character in the database.
     * @param character_id	The id of the character to edit
     * @param name			The name of the character
     * @param quote			A notable quote or saying for the character
     */
    public void editCharacter(long character_id, String name,
                        String quote)
    {
        ContentValues map = new ContentValues();
        map.put("name", name);
        map.put("quote", quote);
        String[] whereArgs = new String[]{Long.toString(character_id)};
        try{
            getWritableDatabase().update("characters", map, "_id=?", whereArgs);
        } catch (SQLException e) {
            Log.e("Error updating new character", e.toString());
        }
    }

    /**
     * Delete a character from the database.
     * @param character_id        The id of the character to delete
     */
    public void deleteCharacter(long character_id) {
        String[] whereArgs = new String[]{Long.toString(character_id)};
        try{
            getWritableDatabase().delete("characters", "_id=?", whereArgs);
        } catch (SQLException e) {
            Log.e("Error deleteing character", e.toString());
        }
    }

    /** Returns the number of Characters */
    public int getCharactersCount(){

        Cursor c = null;
        try {
            c = getReadableDatabase().rawQuery(
                "SELECT count(*) FROM characters",
                null);
            if (0 >= c.getCount()) { return 0; }
            c.moveToFirst();
            return c.getInt(0);
        }
        finally {
            if (null != c) {
                try { c.close(); }
                catch (SQLException e) { }
            }
        }
    }
    /** Return a sorted CharactersCursor */
    public CharactersCursor getCharacters() {
        String sql = CharactersCursor.QUERY;
        SQLiteDatabase d = getReadableDatabase();
        CharactersCursor c = (CharactersCursor) d.rawQueryWithFactory(
            new CharactersCursor.Factory(),
            sql,
            null,
            null);
        c.moveToFirst();
        return c;
    }

}
